/*
 * Ventaspanel.java
 *
 * Created on 22/11/2011, 21:33:51
 */
package org.tri.gui;

import furbelow.SpinningDial;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;
import org.tri.entity.Animal;
import org.tri.entity.Categoria;
import org.tri.entity.Establecimiento;
import org.tri.entity.Venta;
import org.tri.form.TRI;
import org.tri.form.TRIHelper;
import org.tri.gui.worker.ComboFillListener;
import org.tri.gui.worker.ComboFillWorker;
import org.tri.gui.worker.PersistenceListener;
import org.tri.gui.worker.PersistenceWorker;
import org.tri.gui.worker.retrievers.CategoriasDataRetriever;
import org.tri.model.EntityComboBoxModel;
import org.tri.persistence.search.BusquedaAnimal;

/**
 *
 * @author giaco
 */
public class VentasPanel extends javax.swing.JPanel {

    private EntityComboBoxModel<Categoria> categoriasComboBoxModel;
    private DefaultListModel caravanasDisponiblesListModel;
    private DefaultListModel caravanasSeleccionadasListModel;
    private Date fechaActual;
    private SimpleDateFormat formatFecha;
    private Icon loadingIcon;
    private MainFrame frame;

    /** Creates new form Ventaspanel */
    public VentasPanel() {
        //inicializamos el modelo comboBox
        categoriasComboBoxModel = new EntityComboBoxModel<Categoria>(
                Categoria.class, "descripcion" );

        //inicializamos la fecha y el formato de la fecha a mostrar
        fechaActual = new Date();
        formatFecha = new SimpleDateFormat( "dd/MM/yyyy" );

        //Inicializamos los modelos de listas para las listas de caravanas
        caravanasDisponiblesListModel = new DefaultListModel();
        caravanasSeleccionadasListModel = new DefaultListModel();

        //inicializamos el icono de loading
        loadingIcon = new SpinningDial( 20, 20, 10 );

        initComponents();

        //en un thread separado cargamos las categorias
        ComboFillWorker<Categoria> worker = new ComboFillWorker<Categoria>(
                categoriasComboBoxModel, new CategoriasDataRetriever() );

        worker.addComboFillListener( new ComboFillCategoriaHandler() );

        //ejectumos el worker
        worker.execute();

    }//end constructor

    public VentasPanel( MainFrame frame ) {
        this();

        this.frame = frame;

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings ( "unchecked" )
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        jPCentral = new javax.swing.JPanel();
        jPDatos = new javax.swing.JPanel();
        jLdestinatario = new javax.swing.JLabel();
        jTFdestinatario = new javax.swing.JTextField();
        jLrenspa = new javax.swing.JLabel();
        jFTFRenspa = new javax.swing.JFormattedTextField();
        jLcategoria = new javax.swing.JLabel();
        jCBcategoria = new javax.swing.JComboBox();
        jLfecha = new javax.swing.JLabel();
        jLtoday = new javax.swing.JLabel();
        filler1 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 0), new java.awt.Dimension(32767, 0));
        filler11 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 15), new java.awt.Dimension(0, 15), new java.awt.Dimension(32767, 15));
        filler12 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler13 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        jPSeleccion = new javax.swing.JPanel();
        jLbuscar = new javax.swing.JLabel();
        jTFbuscar = new javax.swing.JTextField();
        jBbuscar = new javax.swing.JButton();
        jLBuscarWaitIcon = new javax.swing.JLabel();
        jLCaravanaInicial = new javax.swing.JLabel();
        jFTFCaravanaInicial = new javax.swing.JFormattedTextField();
        jLCantidad = new javax.swing.JLabel();
        jFTFCantidad = new javax.swing.JFormattedTextField();
        jBagregarLote = new javax.swing.JButton();
        jLLoteWaitIcon = new javax.swing.JLabel();
        jLcaravanas = new javax.swing.JLabel();
        jSPCaravanasDisponibles = new javax.swing.JScrollPane();
        jLCaravanasDisponibles = new javax.swing.JList(caravanasDisponiblesListModel);
        jBagregar = new javax.swing.JButton();
        jBquitar = new javax.swing.JButton();
        jLcaravanasSeleccionadas = new javax.swing.JLabel();
        jSPCaravanasSeleccionadas = new javax.swing.JScrollPane();
        jLCaravanasSeleccionadas = new javax.swing.JList(caravanasSeleccionadasListModel);
        jBLimpiar = new javax.swing.JButton();
        jBguardar = new javax.swing.JButton();
        jBimprimir = new javax.swing.JButton();
        jLGuardarWaitIcon = new javax.swing.JLabel();
        filler5 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 32767));
        filler6 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 32767));
        filler9 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 0), new java.awt.Dimension(32767, 0));
        filler7 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler8 = new javax.swing.Box.Filler(new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 0), new java.awt.Dimension(15, 32767));
        filler3 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 32767));
        filler4 = new javax.swing.Box.Filler(new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 0), new java.awt.Dimension(20, 32767));
        filler2 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 20), new java.awt.Dimension(0, 20), new java.awt.Dimension(32767, 20));
        filler10 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));
        filler14 = new javax.swing.Box.Filler(new java.awt.Dimension(0, 5), new java.awt.Dimension(0, 5), new java.awt.Dimension(32767, 5));

        setLayout(new java.awt.BorderLayout());

        jPCentral.setBorder(null);
        jPCentral.setLayout(new java.awt.GridBagLayout());

        jPDatos.setBorder(javax.swing.BorderFactory.createTitledBorder("Datos"));
        jPDatos.setLayout(new java.awt.GridBagLayout());

        jLdestinatario.setText("Destinatario:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
        jPDatos.add(jLdestinatario, gridBagConstraints);

        jTFdestinatario.setColumns(20);
        jTFdestinatario.setMinimumSize(new java.awt.Dimension(230, 25));
        jTFdestinatario.setNextFocusableComponent(jFTFRenspa);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        jPDatos.add(jTFdestinatario, gridBagConstraints);

        jLrenspa.setText("Renspa:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
        jPDatos.add(jLrenspa, gridBagConstraints);

        jFTFRenspa.setColumns(20);
        jFTFRenspa.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        jFTFRenspa.setMinimumSize(new java.awt.Dimension(230, 25));
        jFTFRenspa.setNextFocusableComponent(jCBcategoria);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        jPDatos.add(jFTFRenspa, gridBagConstraints);

        jLcategoria.setText("Categoría:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 15);
        jPDatos.add(jLcategoria, gridBagConstraints);

        jCBcategoria.setModel( categoriasComboBoxModel );
        jCBcategoria.setNextFocusableComponent(jTFbuscar);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPDatos.add(jCBcategoria, gridBagConstraints);

        jLfecha.setText("Fecha:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPDatos.add(jLfecha, gridBagConstraints);

        jLtoday.setText(formatFecha.format( fechaActual ) );
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 5;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        jPDatos.add(jLtoday, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        jPDatos.add(filler1, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 7;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPDatos.add(filler11, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPDatos.add(filler12, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPDatos.add(filler13, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.weightx = 1.0;
        jPCentral.add(jPDatos, gridBagConstraints);

        jPSeleccion.setBorder(javax.swing.BorderFactory.createTitledBorder("Selección"));
        jPSeleccion.setLayout(new java.awt.GridBagLayout());

        jLbuscar.setText("Buscar:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPSeleccion.add(jLbuscar, gridBagConstraints);

        jTFbuscar.setColumns(10);
        jTFbuscar.setMinimumSize(new java.awt.Dimension(120, 25));
        jTFbuscar.setNextFocusableComponent(jBbuscar);
        jTFbuscar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBbuscarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        jPSeleccion.add(jTFbuscar, gridBagConstraints);

        jBbuscar.setText("Buscar");
        jBbuscar.setNextFocusableComponent(jFTFCaravanaInicial);
        jBbuscar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBbuscarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
        jPSeleccion.add(jBbuscar, gridBagConstraints);

        jLBuscarWaitIcon.setMaximumSize(new java.awt.Dimension(25, 25));
        jLBuscarWaitIcon.setMinimumSize(new java.awt.Dimension(25, 25));
        jLBuscarWaitIcon.setPreferredSize(new java.awt.Dimension(25, 25));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 5);
        jPSeleccion.add(jLBuscarWaitIcon, gridBagConstraints);

        jLCaravanaInicial.setText("Caravana inicial:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPSeleccion.add(jLCaravanaInicial, gridBagConstraints);

        jFTFCaravanaInicial.setColumns(8);
        try {
            jFTFCaravanaInicial.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.MaskFormatter("UU###U###")));
        } catch (java.text.ParseException ex) {
            ex.printStackTrace();
        }
        jFTFCaravanaInicial.setMinimumSize(new java.awt.Dimension(98, 25));
        jFTFCaravanaInicial.setNextFocusableComponent(jFTFCantidad);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 10;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPSeleccion.add(jFTFCaravanaInicial, gridBagConstraints);

        jLCantidad.setText("Cantidad:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPSeleccion.add(jLCantidad, gridBagConstraints);

        jFTFCantidad.setColumns(5);
        jFTFCantidad.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        jFTFCantidad.setMinimumSize(new java.awt.Dimension(65, 25));
        jFTFCantidad.setNextFocusableComponent(jBagregarLote);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 10;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        jPSeleccion.add(jFTFCantidad, gridBagConstraints);

        jBagregarLote.setText("Agregar Lote");
        jBagregarLote.setNextFocusableComponent(jBLimpiar);
        jBagregarLote.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBagregarLoteActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 12;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(0, 5, 0, 0);
        jPSeleccion.add(jBagregarLote, gridBagConstraints);

        jLLoteWaitIcon.setMaximumSize(new java.awt.Dimension(25, 25));
        jLLoteWaitIcon.setMinimumSize(new java.awt.Dimension(25, 25));
        jLLoteWaitIcon.setPreferredSize(new java.awt.Dimension(25, 25));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 12;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = new java.awt.Insets(5, 0, 5, 0);
        jPSeleccion.add(jLLoteWaitIcon, gridBagConstraints);

        jLcaravanas.setText("Carvanas disponibles:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPSeleccion.add(jLcaravanas, gridBagConstraints);

        jSPCaravanasDisponibles.setMinimumSize(new java.awt.Dimension(258, 130));

        jSPCaravanasDisponibles.setViewportView(jLCaravanasDisponibles);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 5;
        gridBagConstraints.gridheight = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPSeleccion.add(jSPCaravanasDisponibles, gridBagConstraints);

        jBagregar.setText("Agregar >>");
        jBagregar.setNextFocusableComponent(jBquitar);
        jBagregar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBagregarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPSeleccion.add(jBagregar, gridBagConstraints);

        jBquitar.setText("<< Quitar");
        jBquitar.setNextFocusableComponent(jBagregar);
        jBquitar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBquitarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 7;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        jPSeleccion.add(jBquitar, gridBagConstraints);

        jLcaravanasSeleccionadas.setText("Caravanas seleccionadas:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        jPSeleccion.add(jLcaravanasSeleccionadas, gridBagConstraints);

        jSPCaravanasSeleccionadas.setViewportView(jLCaravanasSeleccionadas);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 5;
        gridBagConstraints.gridheight = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        jPSeleccion.add(jSPCaravanasSeleccionadas, gridBagConstraints);

        jBLimpiar.setText("Limpiar");
        jBLimpiar.setNextFocusableComponent(jBguardar);
        jBLimpiar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBLimpiarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 10;
        jPSeleccion.add(jBLimpiar, gridBagConstraints);

        jBguardar.setText("Guardar");
        jBguardar.setNextFocusableComponent(jBimprimir);
        jBguardar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBguardarActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 10;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
        jPSeleccion.add(jBguardar, gridBagConstraints);

        jBimprimir.setText("Guardar e Imprimir");
        jBimprimir.setNextFocusableComponent(jTFdestinatario);
        jBimprimir.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jBimprimirActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 11;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        jPSeleccion.add(jBimprimir, gridBagConstraints);

        jLGuardarWaitIcon.setMaximumSize(new java.awt.Dimension(25, 25));
        jLGuardarWaitIcon.setMinimumSize(new java.awt.Dimension(25, 25));
        jLGuardarWaitIcon.setPreferredSize(new java.awt.Dimension(25, 25));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 13;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
        gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
        jPSeleccion.add(jLGuardarWaitIcon, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weighty = 1.0;
        jPSeleccion.add(filler5, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 8;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weighty = 1.0;
        jPSeleccion.add(filler6, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 9;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.gridwidth = 3;
        gridBagConstraints.weighty = 0.1;
        jPSeleccion.add(filler9, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 11;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler7, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 14;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 11;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler8, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 6;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridheight = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler3, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 8;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridheight = 5;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler4, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 7;
        gridBagConstraints.gridy = 6;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler2, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 12;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler10, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 9;
        gridBagConstraints.gridwidth = 12;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        jPSeleccion.add(filler14, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.1;
        gridBagConstraints.weighty = 0.1;
        jPCentral.add(jPSeleccion, gridBagConstraints);

        add(jPCentral, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

    private void jBguardarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBguardarActionPerformed
        generarYGuardar( false );

    }//GEN-LAST:event_jBguardarActionPerformed

    private void jBagregarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBagregarActionPerformed
        //hago una lista de los elementos a agregar
        int[] seleccionados = jLCaravanasDisponibles.getSelectedIndices();

        //comprobamos si se superó el máximo de caravanas 
        int extra = comprobarCantidadMaxima( seleccionados.length );

        if ( extra > 0 )
            seleccionados = Arrays.copyOf( seleccionados,
                                           seleccionados.length - extra );

        //los agrego en la lista de seleccionados y los elimino de la lista 
        //a seleccionar
        for ( int i = seleccionados.length; i > 0; i-- )
            caravanasSeleccionadasListModel.addElement(
                    caravanasDisponiblesListModel.remove(
                    seleccionados[i - 1] ) );

    }//GEN-LAST:event_jBagregarActionPerformed

    private void jBquitarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBquitarActionPerformed
        //hago una lista de los elementos a quitar
        int[] seleccionados = jLCaravanasSeleccionadas.getSelectedIndices();

        //los elimino de la lista de seleccionados y los agrego en la 
        //lista a seleccionar
        for ( int i = seleccionados.length; i > 0; i-- )
            caravanasDisponiblesListModel.addElement(
                    caravanasSeleccionadasListModel.remove( 
                    seleccionados[i - 1] ) );

    }//GEN-LAST:event_jBquitarActionPerformed

    private void jBagregarLoteActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBagregarLoteActionPerformed
        if ( !jFTFCaravanaInicial.isEditValid() )
            JOptionPane.showMessageDialog( this,
                                           "Debe ingresar un caravana inicial.",
                                           "Datos insuficientes",
                                           JOptionPane.INFORMATION_MESSAGE );
        else if ( jFTFCantidad.getValue() == null )
            JOptionPane.showMessageDialog( this, "Debe ingresar una cantidad.",
                                           "Datos insuficientes",
                                           JOptionPane.INFORMATION_MESSAGE );
        else {
            //tareas previas de gui
            fireLoteTriggers( true );

            //obtengo la caravana inicial
            String caravanaInicial = (String)jFTFCaravanaInicial.getValue();

            //obtengo la cantidad
            int cantidad = Math.abs(
                    ( (Long)jFTFCantidad.getValue() ).intValue() );
            int numFinal = Integer.parseInt( caravanaInicial.substring( 6 ) )
                           + cantidad - 1;

            //calculo la caravana final
            String caravanaFinal = String.format(
                    "%s%c%03d",
                    caravanaInicial.substring( 0, 5 ),
                    caravanaInicial.charAt( 5 ) + numFinal / 1000,
                    numFinal % 1000 );

            //realizo la busqueda
            BusquedaAnimal busqueda = new BusquedaAnimal();
            busqueda.porEstablecimiento( frame.getEstablecimiento() );
            busqueda.porCaravanasEnRango( caravanaInicial, caravanaFinal );
            busqueda.porVendido( false );
            busqueda.porViva( true );

            //obtenemos los animales en un thread aparte
            SwingWorker worker = new AnimalLoteRetrieveWorker( busqueda );

            worker.execute();

        }

    }//GEN-LAST:event_jBagregarLoteActionPerformed

    private void jBbuscarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jBbuscarActionPerformed
        //realizamos las tareas de GUI para indicar que se inició la busqueda
        fireBusquedaTriggers( true );

        //obtenemos el criterio de la busqueda de caravana
        String criterio = jTFbuscar.getText();

        //limpiamos la lista anterior
        caravanasDisponiblesListModel.removeAllElements();

        //armamos la busqueda
        BusquedaAnimal busqueda = new BusquedaAnimal();

        if ( criterio.length() > 0 )
            busqueda.porCaravana( criterio );

        busqueda.porEstablecimiento( frame.getEstablecimiento() );
        busqueda.porVendido( false );
        busqueda.porViva( true );

        //obtenemos los animales en un thread aparte
        SwingWorker worker = new BusquedaAnimalRetrieveWorker( busqueda );

        worker.execute();

    }//GEN-LAST:event_jBbuscarActionPerformed

    private void jBLimpiarActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBLimpiarActionPerformed
        if ( JOptionPane.showConfirmDialog(
                this,
                "¿Seguro que desea limpiar el formulario?", "Confirmación",
                JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE )
             == JOptionPane.YES_OPTION )
            limpiarPanel();

    }//GEN-LAST:event_jBLimpiarActionPerformed

    private void jBimprimirActionPerformed( java.awt.event.ActionEvent evt ) {//GEN-FIRST:event_jBimprimirActionPerformed
       generarYGuardar( true );
        
    }//GEN-LAST:event_jBimprimirActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.Box.Filler filler1;
    private javax.swing.Box.Filler filler10;
    private javax.swing.Box.Filler filler11;
    private javax.swing.Box.Filler filler12;
    private javax.swing.Box.Filler filler13;
    private javax.swing.Box.Filler filler14;
    private javax.swing.Box.Filler filler2;
    private javax.swing.Box.Filler filler3;
    private javax.swing.Box.Filler filler4;
    private javax.swing.Box.Filler filler5;
    private javax.swing.Box.Filler filler6;
    private javax.swing.Box.Filler filler7;
    private javax.swing.Box.Filler filler8;
    private javax.swing.Box.Filler filler9;
    private javax.swing.JButton jBLimpiar;
    private javax.swing.JButton jBagregar;
    private javax.swing.JButton jBagregarLote;
    private javax.swing.JButton jBbuscar;
    private javax.swing.JButton jBguardar;
    private javax.swing.JButton jBimprimir;
    private javax.swing.JButton jBquitar;
    private javax.swing.JComboBox jCBcategoria;
    private javax.swing.JFormattedTextField jFTFCantidad;
    private javax.swing.JFormattedTextField jFTFCaravanaInicial;
    private javax.swing.JFormattedTextField jFTFRenspa;
    private javax.swing.JLabel jLBuscarWaitIcon;
    private javax.swing.JLabel jLCantidad;
    private javax.swing.JLabel jLCaravanaInicial;
    private javax.swing.JList jLCaravanasDisponibles;
    private javax.swing.JList jLCaravanasSeleccionadas;
    private javax.swing.JLabel jLGuardarWaitIcon;
    private javax.swing.JLabel jLLoteWaitIcon;
    private javax.swing.JLabel jLbuscar;
    private javax.swing.JLabel jLcaravanas;
    private javax.swing.JLabel jLcaravanasSeleccionadas;
    private javax.swing.JLabel jLcategoria;
    private javax.swing.JLabel jLdestinatario;
    private javax.swing.JLabel jLfecha;
    private javax.swing.JLabel jLrenspa;
    private javax.swing.JLabel jLtoday;
    private javax.swing.JPanel jPCentral;
    private javax.swing.JPanel jPDatos;
    private javax.swing.JPanel jPSeleccion;
    private javax.swing.JScrollPane jSPCaravanasDisponibles;
    private javax.swing.JScrollPane jSPCaravanasSeleccionadas;
    private javax.swing.JTextField jTFbuscar;
    private javax.swing.JTextField jTFdestinatario;
    // End of variables declaration//GEN-END:variables
    
    /**
     * Realiza las tareas de GUI previas/posteriores a la busqueda. Esto implica
     * deshabilitar/habilitar los controles de busqueda y mostrar una animación
     * de espera.
     * @param inicio indica si se deben usar los triggers de inicio o de fin.
     */
    private void fireBusquedaTriggers( boolean inicio ) {
        if ( inicio ) {
            //deshabilitamos la barra de busqueda
            jTFbuscar.setEditable( false );
            jBbuscar.setEnabled( false );

            //colocamos el icono de espera
            jLBuscarWaitIcon.setEnabled( true );
            jLBuscarWaitIcon.setIcon( loadingIcon );

        } else {
            //rehabilitamos la barra de busqueda
            jTFbuscar.setEditable( true );
            jBbuscar.setEnabled( true );

            //quitamos el icono de espera
            jLBuscarWaitIcon.setEnabled( false );

        }

    }//end método fireBusquedaTriggers

    /**
     * Realiza las tareas de GUI previas/posteriores al agregado por lote. 
     * Esto implica deshabilitar/habilitar los controles y mostrar una animación
     * de espera.
     * @param inicio indica si se deben usar los triggers de inicio o de fin.
     */
    private void fireLoteTriggers( boolean inicio ) {
        if ( inicio ) {
            //deshabilitamos los controles
            jFTFCaravanaInicial.setEditable( false );
            jFTFCantidad.setEnabled( false );
            jBagregarLote.setEnabled( false );

            //tambien deshabilitamos los botones de guardar
            jBguardar.setEnabled( false );
            jBimprimir.setEnabled( false );

            //colocamos el icono de espera
            jLLoteWaitIcon.setEnabled( true );
            jLLoteWaitIcon.setIcon( loadingIcon );

        } else {
            //rehabilitamos los controles
            jFTFCaravanaInicial.setEditable( true );
            jFTFCantidad.setEnabled( true );
            jBagregarLote.setEnabled( true );
            jBagregarLote.requestFocus();

            jBguardar.setEnabled( true );
            jBimprimir.setEnabled( true );

            //quitamos el icono de espera
            jLLoteWaitIcon.setEnabled( false );

        }

    }//end método fireLoteTriggers

    /**
     * Realiza las tareas de GUI previas/posteriores al agregado por lote. 
     * Esto implica deshabilitar/habilitar los controles y mostrar una animación
     * de espera.
     * @param inicio indica si se deben usar los triggers de inicio o de fin.
     */
    private void fireGuardarTriggers( boolean inicio ) {
        if ( inicio ) {
            //deshabilitamos los controles
            jBguardar.setEnabled( false );
            jBimprimir.setEnabled( false );

            //colocamos el icono de espera
            jLGuardarWaitIcon.setEnabled( true );
            jLGuardarWaitIcon.setIcon( loadingIcon );

        } else {
            //rehabilitamos los controles
            jBguardar.setEnabled( true );
            jBimprimir.setEnabled( true );

            //quitamos el icono de espera
            jLGuardarWaitIcon.setEnabled( false );

        }

    }//end método fireGuardarTriggers

    /**
     * Limpia las listas de animales.
     */
    protected void limpiarListas() {
        caravanasDisponiblesListModel.removeAllElements();
        caravanasSeleccionadasListModel.removeAllElements();

    }//end método limpiarListas

    /**
     * Limpia todos los campos del formulario.
     */
    protected void limpiarPanel() {
        jTFdestinatario.setText( "" );
        jFTFRenspa.setValue( null );
        jCBcategoria.setSelectedIndex( -1 );
        jTFbuscar.setText( "" );
        jFTFCantidad.setValue( null );
        jFTFCaravanaInicial.setValue( null );
        limpiarListas();

    }//end método limpiarPanel

    /**
     * Comprueba si la cantidad máxima de caravanas aceptadas por un TRI
     * se superara al agregar una cierta cantidad de animales o no, 
     * mostrando un mensaje de advertencia en caso positivo.
     * @param cantidad cantidad cantidad de animales que se desean agregar.
     * @return cantidad extra de animales sobre el máximo.
     */
    private int comprobarCantidadMaxima( int cantidad ) {
        int total = caravanasSeleccionadasListModel.size() + cantidad;
        int extra = total - TRI.CANT_MAX_CARAVANAS;

        extra = ( extra > 0 ) ? extra : 0;

        if ( extra != 0 )
            JOptionPane.showMessageDialog( this ,String.format( 
                    "Se supero la cantidad máxima de %d caravanas",
                      TRI.CANT_MAX_CARAVANAS ),
                    "No se copleto la operación", JOptionPane.WARNING_MESSAGE );


        return extra;

    }//end método comprobarCantidadMaxima

    /**
     * Genera una venta con los datos del formulario y los hace persistentes
     * en la base de datos.
     * @return venta generada
     */
    private void generarYGuardar( boolean imprimir ) {
        // builder para almacenar los errores
        StringBuilder error = new StringBuilder();

        //obtenemos el establecimiento con el que estamos trabajando
        Establecimiento establecimiento = frame.getEstablecimiento();

        // creamos la venta y seteamos sus propiedades
        Venta venta = establecimiento.crearVenta();

        //controlo que  se halla llenado el campo destinatario
        if ( !jTFdestinatario.getText().equals( "" ) )
            venta.setDestinatario( jTFdestinatario.getText() );
        else
            error.append( "- El campo \"Destinatario\" no fué completado." );

        //controlo que se halla llenado el campo renspaDestinatario
        try {
            jFTFRenspa.commitEdit();
            venta.setRenspaDestinatario( 
                    Math.abs( (Long)jFTFRenspa.getValue() ) );

        } catch ( ParseException pE ) {
            error.append( ( error.length() > 0 ) ? "\n" : "" );
            error.append( "- El campo \"Renspa\" no fué completado." );

        }

        //controlo que se haya seleccionado una categoria
        if ( jCBcategoria.getSelectedIndex() != -1 ) {
            venta.setCategoria( categoriasComboBoxModel.getElemento(
                jCBcategoria.getSelectedIndex() ) );
         
        } else {
            error.append( ( error.length() > 0 ) ? "\n" : "" );
            error.append( "- No se selecciono una \"Categoria\" válida." );
            
        }        

        //transformo la lista de objetos de animales seleccionados
        ArrayList<Animal> animales = new ArrayList<Animal>();
        for ( Object o : caravanasSeleccionadasListModel.toArray() )
            animales.add( (Animal)o );

        //controlo que se hallan seleccionado animales
        if ( !animales.isEmpty() )
            venta.agregarAnimales( animales );
        else {
            error.append( ( error.length() > 0 ) ? "\n" : "" );
            error.append( "- No se ingreso ningúna caravana para la venta." );

        }

        //almacenamos en la base de datos en un thread aparte
        if ( error.length() == 0 ) {
            //eventos de gui previos
            fireGuardarTriggers( true );

            PersistenceWorker worker = new PersistenceWorker( venta, true );
            
            PersistenceHandler handler = new PersistenceHandler( venta,
                                                                 imprimir );

            worker.addPersistenceListener( handler );

            worker.execute();

        } else {
            JOptionPane.showMessageDialog(
                    this, error.toString(),
                    "No se completaron todos los campos", 
                    JOptionPane.WARNING_MESSAGE );

        }

    }//end método guardar
    
    /**
     * Handler para el filler del combo de categorias.
     */
    class ComboFillCategoriaHandler implements ComboFillListener {
        /**
         * {@inheritDoc }
         */
        @Override
        public void doneFillingCombo() {
            //ignore
        
        }//end método doneFillingCombo

        /**
         * {@inheritDoc }
         */
        @Override
        public void errorFillingCombo( ExecutionException ex ) {
            frame.recoverFromFail();
            
        }//end métdo errorFillingCombo

    }//end clase ComboFillCategoriaHandler

    /**
     * Base para los retrievers de animales que se utilizan en este panel
     * para buscar y listar animales que siguen ciertos criterios.
     */
    abstract class AnimalRetrieveWorker extends 
            SwingWorker<List<Animal>, Object> {
        /** Busqueda utilizada para acceder la base de datos. */
        private BusquedaAnimal busqueda;

        /**
         * Inicializa el retriever con la busqueda necesaria.
         * @param busqueda 
         */
        public AnimalRetrieveWorker( BusquedaAnimal busqueda ) {
            this.busqueda = busqueda;

        }//end constructor

        /**
         * {@inheritDoc }
         */
        @Override
        protected List<Animal> doInBackground() throws Exception {
            return busqueda.listarResultados();

        }//end método doInBackground

        /**
         * Actualiza la GUI de acuerdo a los resultados obtenidos.
         */
        @Override
        protected void done() {
            actualizarGUI();

        }//end método done
        
        /**
         * Actualiza la gui de acuerdo a la metodología utilizada para 
         * realizar la carga de animales.
         */
        protected abstract void actualizarGUI();
        
    }//end clase AnimalRetrieveWorker
    
    /**
     * Clase específica que utiliza el agregado por lote para la carga
     * de animales.
     */
    class AnimalLoteRetrieveWorker extends AnimalRetrieveWorker {

        /**
         * Inicializa el retriever con una busqueda.
         * @param busqueda busqueda a utilizar.
         */
        public AnimalLoteRetrieveWorker( BusquedaAnimal busqueda ) {
            super( busqueda );
            
        }//end constructor

        /**
         * {@inheritDoc}
         */
        @Override
        protected void actualizarGUI() {
            try {
                //agregamos los animales a la lista
                List<Animal> animales = get();

                //sacamos de la lista los animales que ya fueron
                //previamente seleccionados
                Iterator<Animal> iter = animales.iterator();

                while ( iter.hasNext() )
                    if ( caravanasSeleccionadasListModel.
                            contains( iter.next() ) )
                        iter.remove();

                //comprobamos si se alcanzo la cantidad máxima
                int extra = comprobarCantidadMaxima( animales.size() );

                if ( extra > 0 )
                    animales.subList( animales.size() - extra,
                                      animales.size() ).clear();

                //agrego los animales a la lista
                for ( Animal animal : animales ) {
                    caravanasSeleccionadasListModel.addElement( animal );
                    caravanasDisponiblesListModel.removeElement( animal );

                }//end for


            } catch ( InterruptedException ex ) {
            } catch ( ExecutionException ex ) {
                frame.recoverFromFail();
                
            }

            //realizamos las tareas de gui para indicar que termino 
            //la busqueda
            fireLoteTriggers( false );

        }//end método actualizarGUI

    }//end clase AnimalLoteRetrieveWorker
    
    /**
     * Clase especifica que carga los animales utilizando la feature de
     * busqueda del panel.
     */
    class BusquedaAnimalRetrieveWorker extends AnimalRetrieveWorker {

        /**
         * Inicializa el retriever con la busqueda a realizar.
         * @param busqueda busqueda a realizar.
         */
        public BusquedaAnimalRetrieveWorker( BusquedaAnimal busqueda ) {
            super( busqueda );

        }//end constructor
        
        /**
         * {@inheritDoc}
         */
        @Override
        protected void actualizarGUI() {
            try {
                //agregamos los animales a la lista
                filtrarYAgregar( get() );

            } catch ( InterruptedException ex ) {
            } catch ( ExecutionException ex ) {
                frame.recoverFromFail();
                
            }

            //realizamos las tareas de gui para indicar que termino la busqueda
            fireBusquedaTriggers( false );

        }//end método actualizarGUI

        private void filtrarYAgregar( List<Animal> animales ) {
            //listo los animales ya seleccionados
            Object[] seleccionados = caravanasSeleccionadasListModel.toArray();

            //los elimino de la lista a cargar
            if ( seleccionados.length > 0 )
                animales.removeAll( Arrays.asList( seleccionados ) );

            //agrego los animales a la lista
            for ( Animal animal : animales )
                caravanasDisponiblesListModel.addElement( animal );

        }//end método filtrarYAgregar

    }//end clase BusquedaAnimalRetrieveWorker
    
    /**
     * Handler que se encarga de realizar las tareas previas a la persistencia
     * de la venta.
     */
    class PersistenceHandler implements PersistenceListener {
        /** Bandera que indica si ocurrió un error. */
        private boolean error;
        /** Venta para guardarla e imprimirla en el caso que se necesite. */
        private Venta venta;
        /** Booleano que indica si se debe imprimir o no el TRI */
        private boolean imprimir;
        
        /**
         * Inicializa el handler indicado la venta para guardar y si imprimir
         * o no el TRI.
         * @param venta venta a guardar.
         * @param imprimir bandera que indica si imprimir o no el TRI.
         */
        private PersistenceHandler(  Venta venta, boolean imprimir ) {
            this.venta = venta;
            this.imprimir = imprimir;
            
        }//end constructor
        
        /**
         * {@inheritDoc}
         */
        @Override
        public void donePersisting() {
            //rehabilitamos la gui
            fireGuardarTriggers( false );
            
            if ( error )
                return;

            //limpiamos el formulario
            limpiarPanel();           
            
            //si se mando para imprimir imprimimos, si no consultamos si se
            //desea guardar el TRI de todas maneras.
            if ( this.imprimir )                    
                TRIHelper.guardarEImprimir( venta );                
            
            else if ( JOptionPane.showConfirmDialog( frame,
                                                "¿Desea generar el TRI?",
                                                "Guardar",
                                                JOptionPane.YES_NO_OPTION )
                 == JOptionPane.YES_OPTION )
                try {
                    TRIHelper.guardar( venta );

                } catch ( Exception ex ) {
                    //informamos que se guardo con éxito
                    JOptionPane.showMessageDialog( VentasPanel.this,
                                                   "No se pudo generar el TRI. "
                                                   + "Intente generarlo "
                                                   + "nuevamente desde el "
                                                   + "panel de listados.",
                                                   "Error al generar TRI",
                                                   JOptionPane.WARNING_MESSAGE );

                }
            //informamos que se guardo con éxito
            JOptionPane.showMessageDialog( VentasPanel.this, 
                                           "Venta guardada.",      
                                           "Completado", 
                                           JOptionPane.INFORMATION_MESSAGE );
                                    
        }//end método donePersisting
        
        /**
         * {@inheritDoc}
         */
        @Override
        public void errorPersisting( ExecutionException ex ) {
            error = true;    
            
            frame.recoverFromFail();
            
        }//end método errorPersisting
        
    }//end clase PersistenceHandler

}//end clase VentasPanel
